package org.ccay.vfs;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.util.Messages;
import org.ccay.core.io.CompressScheme;
import org.ccay.core.io.CompressVFSFileObject;
import org.ccay.core.io.FileStoreType;
import org.ccay.core.io.VFSFileObject;
import org.springframework.util.Assert;

public class CompressApacheVFSFileObject extends ApacheVFSFileObject implements CompressVFSFileObject{
	/**
	 * 压缩文件内部路径
	 */
	private String compressPath;
	/**
	 * 压缩文件scheme
	 */
	private CompressScheme compressScheme;
	
	/**
	 * 压缩文件 VFS对象
	 */
	private FileObject compressFileObject;

	
	public CompressApacheVFSFileObject(VFSFileObject parentFileObject,String compressPath,CompressScheme compressScheme) {
		super(parentFileObject,parentFileObject.getStoreType());
		validateAndSet(compressPath,compressScheme);
		resolveFile();
	}
	
	private void validateAndSet(String compressPath,CompressScheme compressScheme){
		if(compressPath == null){
			compressPath = "";
		}
		this.compressPath = compressPath.startsWith("/") ? compressPath.substring(1) : compressPath;;
		
		Assert.notNull(compressScheme);
		this.compressScheme = compressScheme;
	}
	
	private void resolveFile(){
		compressFileObject = VFS.resolveFile(super.getModule(),super.getStoreType(),super.getRelativePath(),compressPath,compressScheme.getScheme());
	}
	

	@Override
	public String getCompressScheme() {
		return compressScheme.getScheme();
	}

	@Override
	public String getCompressPath() {
		return compressPath;
	}
	
	@Override
	public String getDisplayName() {
		return getBaseName();
	}

	@Override
	public String getBaseName() {
		return compressFileObject.getName().getBaseName();
	}

	@Override
	public String getModule() {
		return super.getModule();
	}
	
	@Override
	public String getRootURI() {
		return super.getRootURI()+"/"+super.getRelativePath();
	}

	@Override
	public String getLocalRootAbsolutePath(){
		switch (super.getStoreType()) {
		case WROK:
			return getRootURI().substring(VFS.LOCAL_URL_PREFIX.length());
		default:
			throw new VFSException("NotLocalFileSystem","NotLocalFileSystem");
		}
	}
	
	@Override
	public String getLocalAbsolutePath(){
		switch (super.getStoreType()) {
		case WROK:
			return getLocalRootAbsolutePath() + "!/" + compressPath;
		default:
			throw new VFSException("NotLocalFileSystem","NotLocalFileSystem");
		}
	}
	
	@Override
	public String getAbsolutePath() {
		return super.getAbsolutePath() + "!/" + compressPath;
	}

	@Override
	public String getRelativePath() {
		return getCompressPath();
	}

	@Override
	public String getExtension() {
		return compressFileObject.getName().getExtension();
	}

	@Override
	public String getScheme() {
		return compressFileObject.getName().getScheme();
	}

	@Override
	public String getURI() {
		return compressFileObject.getName().getURI();
	}

	@Override
	public boolean isFile(){
		try {
			return compressFileObject.isFile();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	
	@Override
	public boolean isFolder() {
		try {
			return compressFileObject.isFolder();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	

	@Override
	public long getSize() {
		try {
			return compressFileObject.getContent().getSize();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public Date getLastModifiedTime() {
		try {
			return new Date(compressFileObject.getContent().getLastModifiedTime());
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	
	@Override
	public String getContentType() {
		try {
			return compressFileObject.getContent().getContentInfo().getContentType();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public InputStream getInputStream() {
		try {
			return compressFileObject.getContent().getInputStream();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public OutputStream getOutputStream() {
		throw createException("vfs.provider/write-append-not-supported.error");
	}

	@Override
	public void close() {
		try {
			super.close();
			compressFileObject.close();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}

	}

	@Override
	public FileStoreType getStoreType() {
		return super.getStoreType();
	}

	@Override
	public boolean exists() {
		try {
			return compressFileObject.exists();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	public void setDisplayName(String displayName) {
		throw new VFSException("compressVFO","Not support This Method!"); 
	}

	public boolean isInline() {
		return super.isInline();
	}

	public void setInline(boolean inline) {
		super.setInline(inline);
	}


	@Override
	public VFSFileObject copyToArchive() {
		return copyTo(FileStoreType.ARCHIVE);
	}


	@Override
	public VFSFileObject copyToWork() {
		return copyTo(FileStoreType.WROK);
	}


	@Override
	public VFSFileObject copyToTemp() {
		return copyTo(FileStoreType.TEMP);
	}

	private VFSFileObject copyTo(FileStoreType targetStoreType){
		String fileToDir = null;
		if(super.getExtension().isEmpty()){
			fileToDir = super.getRelativePath() + System.currentTimeMillis();
		}else{
			fileToDir = super.getRelativePath().substring(0, super.getRelativePath().length() - super.getExtension().length() - 1 );
		}
		ApacheVFSFileObject targetFileObj = new ApacheVFSFileObject(super.getModule(),fileToDir	+ "/" + this.getCompressPath(),
				targetStoreType);
		try {
			targetFileObj.getFileObject().copyFrom(this.compressFileObject, Selectors.SELECT_ALL);
			return targetFileObj;
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	public FileObject getFileObject() {
		return compressFileObject;
	}

	@Override
	public boolean delete() {
		throw createException("vfs.provider/delete-not-supported.error");
	}
	
	@Override
	public int deleteAll() {
		throw createException("vfs.provider/delete-not-supported.error");
	}
	
	private VFSException createException(String vfsCode){
		return new VFSException(vfsCode,Messages.getString(vfsCode));
	}

	@Override
	public String toString() {
		return "CompressApacheVFSFileObject [compressFileObject=" + compressFileObject + ", compressScheme="
				+ compressScheme + ", compressPath=" + compressPath + "]";
	}

}
